package org.redis.service;


import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.redis.utils.JsonUtils;

import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.function.Function;

/**
 * @author admin
 */
public interface RedisService {
    /**
     * json 序列化对象
     */
    ObjectMapper mapper = JsonUtils.mapper;

    /**
     *  通用的 类型转换方法
     * @param t
     * @param type
     * @param <T>
     * @param <R>
     * @return
     * @throws IOException
     */
    default <T extends Object,R> R convert( T t ,Class<R> type){
        try{
            if(t instanceof Number){
                return (R)t;
            }else if(t instanceof String){
                return mapper.readValue((String)t, type);
            }
            return mapper.readValue((JsonParser) t, type);
        }catch (IOException e){
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 从redis中获取值 (redis String 类型)
     * 如果不存在则通过 t 自动同步加载
     *
     * @param keys
     * @param t
     * @param <T>
     * @param <R>
     * @return
     */
    <T extends RedisKeys, R> R getAndLoader(T keys, Function<T, R> t);

    /**
     * 从redis中获取值 (redis String 类型)
     * 如果不存在则通过 t 自动异步加载
     *
     * @param keys
     * @param t
     * @param <T>
     * @param <R>
     * @return
     */
    <T extends RedisKeys, R> R getAndAsyncLoader(T keys, Function<T, R> t);

    /**
     * 存入list 集合
     *
     * @param keys
     * @param data
     * @param length
     */
    <T extends RedisKeys> void addList(T keys, List<Integer> data, Integer length);

    /**
     * List 增加单个值
     *
     * @param keys
     * @param <T>
     */
    <T extends RedisKeys> void addList(T keys);

    /**
     * List 删除单个值
     *
     * @param keys
     * @param <T>
     */
    <T extends RedisKeys> void deleteList(T keys);

    /**
     * 存入set 集合
     *
     * @param keys
     * @param data
     */
    <T extends RedisKeys, V extends Collection<Integer>> void addSet(T keys, V data);

    /**
     * 添加 如果超过指定大小则清空
     *
     * @param keys
     * @return
     */
    <T extends RedisKeys, V extends Collection<Integer>> void addSetClear(T keys, V data, Long length);

    /**
     * 差集并存
     *
     * @param key1
     * @param key2
     * @return
     */
    <T extends RedisKeys> Long differenceAndStore(T key1, T key2, T store);

    /**
     * 获取差集
     *
     * @param key1
     * @param key2
     * @return
     */
    <T extends RedisKeys> Set<Integer> difference(T key1, T key2);

    /**
     * 获取元素
     *
     * @param key
     * @param count
     * @return
     */
    <T extends RedisKeys> Set<Integer> randomMembers(T key, Integer count);

    /**
     * 获取所有set数据
     *
     * @param key
     * @return
     */
    <T extends RedisKeys> Set<Integer> getAllMembers(T key);

    /**
     * 删除set 集合中的 key.setValue()的元素
     *
     * @param key
     * @return
     */
    <T extends RedisKeys> void removeMembers(T key);

    /**
     * 向 set 增加一个 key.setValue()的元素
     *
     * @param key
     * @param <T>
     */
    <T extends RedisKeys> void addMembers(T key);

    /**
     * 获取 List集合中 索引位置为 start 到 end 列表集合元素
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    <T extends RedisKeys> List<Integer> getList(T key, Long start, Long end);

    /**
     * 删除key
     *
     * @param key
     * @param <T>
     */
    <T extends RedisKeys> void deleteKey(T key);

    /**
     * 获取redis
     * @param  key
     * @return true 成功
     */
    <T extends RedisKeys> String get(T key);

    /**
     * 获取redis值返回指定类型数据
     * @param key
     * @param type
     * @param <T>
     * @param <R>
     * @return
     */
    <T extends RedisKeys,R> R get(T key,Class<R> type);

    /**
     * 如果key不存在则返回 true
     * @param key
     * @param <T>
     * @return
     */
    <T extends RedisKeys>Boolean ifAbsent(T key);

    /**
     *  增加
     * @param key
     * @param <T>
     */
    <T extends RedisKeys>void add(T key);

    /**
     *  设置过期时间
     * @param key
     * @param <T>
     */
    <T extends RedisKeys>void expire(T key);

    /**
     *  自增 INC
     * @param key
     * @param <T>
     */
    <T extends RedisKeys> Long addInc(T key);
}
